/**
 * DSM - Distributed Search Manager
 * Developed by Milspec Research International Pty Ltd
 * $Author: gsingh $
 * $Revision: 1.1 $
 * $Date: 2005/09/15 06:44:44 $
 * (c)Copyright 2004
 * education.au limited
 * DEST
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the names education.au limited, DEST nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 * To the extent permitted by law, the copyright owners of this software and
 * its contributors:
 * (i) exclude all warranties in relation to the software; and
 * (ii) exclude liability for all losses, costs, expenses and damages arising
 * in any way from the use of the software whether arising from or in
 * relation to breach of contract, negligence or any other tort, in equity
 * or otherwise. If the software is in breach of a warranty which is
 * implied by law, the copyright owners and contributors liability is
 * limited to the replacement of the software.
 *
 * @author	gsingh
 */

package au.edu.educationau.opensource.dsm.obj;

import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Turns a XCQL tree into a DSM criteria object
 * 
 * @examples
 * 
 * ENGLISH> all of the words: cat dog CQL> cql.serverChoice all "cat dog"
 * 
 * Returns:
 * 
 * <searchClause> <index>cql.serverChoice</index> <relation> <value>all</value>
 * </relation> <term>cat dog</term> </searchClause>
 * 
 * ENGLISH> any of the words: cat dog CQL> cql.serverChoice any "cat dog"
 * 
 * Returns:
 * 
 * <searchClause> <index>cql.serverChoice</index> <relation> <value>any</value>
 * </relation> <term>cat dog</term> </searchClause>
 * 
 * ENGLISH> exact phrase: cat dog CQL> cql.serverChoice = "cat dog"
 * 
 * Returns:
 * 
 * <searchClause> <index>cql.serverChoice</index> <relation> <value>=</value>
 * </relation> <term>cat dog</term> </searchClause>
 * 
 * 
 * What this handler does:
 * 
 * This handler will ONLY process queries by the &lt;searchClause&gt; element.
 * Then, it takes the relation field and converts that into a DSM keyword
 * constraint. Following that, the term values are added to the arraylist and
 * then converted into a list of terms for the query string.
 * 
 */

public class CQLCriteriaHandler extends DefaultHandler {
	private ArrayList terms = new ArrayList();
	private boolean isSearchClause = false;
	private String startElement = "";
	private String previousElement = "";
	private String constraint = ""; // all, any, phrase

	/** Returns the terms to search on */
	public String getTerms() {
		StringBuffer keywords = new StringBuffer();
		for (int i = 0; i < terms.size(); i++) {
			keywords.append((String) terms.get(i));

			if (i < (terms.size() - 1)) {
				keywords.append(" ");
			}
		}
		return keywords.toString();
	}

	/** Returns the constraint */
	public String getKeywordConstraint() {
		return constraint;
	}

	/**
	 * Event based parsing -
	 * 
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void characters(char[] ch, int ch_start, int ch_length) throws SAXException {
		String val = String.copyValueOf(ch, ch_start, ch_length);

		if (previousElement.equals("boolean") && startElement.equals("value") && this.constraint.length() == 0) {
			// Constraint NOT set yet.

			if (val.equals("=")) {
				this.constraint = "phrase";
			} else if (val.equals("or")) {
				this.constraint = "any";
			} else {
				this.constraint = "all";
			}

			// Flog.info("", "CONSTRAINT= "+this.constraint);
		}

		if (isSearchClause) {
			if (startElement.equals("term")) {
				this.terms.add(val);
			}

			if (previousElement.equals("relation") && startElement.equals("value") && this.constraint.length() == 0) {
				// Constraint NOT set yet.

				if (val.equals("=")) {
					this.constraint = "phrase";
				} else if (val.equals("any")) {
					this.constraint = "any";
				} else {
					this.constraint = "all";
				}
				// Flog.info("", "CONSTRAINT= "+this.constraint);
			}
		}

		previousElement = startElement;
		startElement = "";
	}

	/**
	 * Event based parsing -
	 * 
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void ignorableWhitespace(char[] ch, int ch_start, int ch_length) throws SAXException {
	}

	/**
	 * Event based parsing -
	 * 
	 * @param uri
	 * @param localName
	 * @param qName
	 * @exception SAXException
	 */
	public void endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName) throws SAXException {
		if (localName.equals("searchClause")) {
			isSearchClause = false;
			// Flog.info("", "SEARCH CLAUSE END");
		}
	}

	/**
	 * Event based parsing -
	 * 
	 * @param target
	 * @param data
	 * @exception SAXException
	 */
	public void processingInstruction(String target, String data) throws SAXException {
	}

	/**
	 * Event based parsing -
	 * 
	 * @param uri
	 * @param localName
	 * @param qName
	 * @param attr
	 * @exception SAXException
	 */
	public void startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, Attributes attr) throws SAXException {
		if (localName.equals("searchClause")) {
			isSearchClause = true;
			// Flog.info("", "SEARCH CLAUSE START");
		}
		this.startElement = localName;
	}

}
